﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NetworkingLibrary.Clients.UDP;
using NetworkingLibrary.Servers.UDP;
using NetworkingLibrary.Messages;
using NetworkingLibrary.Messages.Specialised.Game;
using NetworkingLibrary.Events;
using NetworkingLibrary.Exceptions;

using System.Net;
using System.Threading;

namespace UDP_Test_Application
{
    class Program
    {
        const int LoopDelay = 150;
        static int ServerPort = 56789;
        static int Client1Port = 56788;
        static int Client2Port = 56787;

        static Random Rand = new Random();

        static IPAddress MulticastAddress = IPAddress.Parse("224.5.6.7");
        static IPAddress LocalMachineAddress = Dns.GetHostAddresses(Dns.GetHostName()).First();

        static void Main(string[] args)
        {
            UDPServer TheUDPServer = new UDPServer();
            TheUDPServer.OnClientConnect += new ClientConnectDelegate(TheUDPServer_OnClientConnect);
            TheUDPServer.OnClientDisconnect += new ClientDisconnectDelegate(TheUDPServer_OnClientDisconnect);
            TheUDPServer.OnError += new ErrorDelegate(TheUDPServer_OnError);
            TheUDPServer.OnMaxConnections += new MaxConnectionsDelegate(TheUDPServer_OnMaxConnections);
            TheUDPServer.OnMessageReceived += new MessageReceivedDelegate(TheUDPServer_OnMessageReceived);

            //if (TheUDPServer.Start(ServerPort, null))
            if (TheUDPServer.Start(ServerPort, null, 10, MulticastAddress, 1))
            {
                Console.WriteLine("UDP server started.");
                
                UDPClient UDPClient1 = new UDPClient(Client1Port);
                UDPClient1.OnConnect += new ClientConnectDelegate(UDPClient1_OnConnect);
                UDPClient1.OnDisconnect += new ClientDisconnectDelegate(UDPClient1_OnDisconnect);
                UDPClient1.OnError += new ErrorDelegate(UDPClient1_OnError);
                UDPClient1.OnMessageReceived += new MessageReceivedDelegate(UDPClient1_OnMessageReceived);

                //if (UDPClient1.Connect(ServerPort, LocalMachineAddress, true))
                if (UDPClient1.Connect(ServerPort, MulticastAddress, false, true, 1))
                {
                    UDPClient UDPClient2 = new UDPClient(Client2Port);
                    UDPClient2.OnConnect += new ClientConnectDelegate(UDPClient2_OnConnect);
                    UDPClient2.OnDisconnect += new ClientDisconnectDelegate(UDPClient2_OnDisconnect);
                    UDPClient2.OnError += new ErrorDelegate(UDPClient2_OnError);
                    UDPClient2.OnMessageReceived += new MessageReceivedDelegate(UDPClient2_OnMessageReceived);

                    //if (UDPClient2.Connect(ServerPort, LocalMachineAddress, true))
                    if (UDPClient2.Connect(ServerPort, MulticastAddress, false, true, 1))
                    {
                        bool Terminate = false;
                        while (!Terminate)
                        {
                            Console.WriteLine();
                            Console.WriteLine();
                            Console.WriteLine("-----------------------------------------");
                            Console.WriteLine();
                            Console.WriteLine("Press enter to send test message or escape to exit.");
                            ConsoleKeyInfo Input = Console.ReadKey();
                            if (Input.Key == ConsoleKey.Enter)
                            {
                                TestMessage NewMessage = new TestMessage(new Random().Next(), "Your random number is : ");
                                //UDPClient1.Send(NewMessage);
                                //Thread.Sleep(15);
                                //NewMessage = new TestMessage(new Random().Next(), "Your random number is : ");
                                //UDPClient2.Send(NewMessage);
                                UDPClient2.SendTo(LocalMachineAddress, Client1Port, NewMessage);
                                Thread.Sleep(LoopDelay);
                            }
                            else if (Input.Key == ConsoleKey.Escape)
                            {
                                Terminate = true;
                            }
                        }

                        if (!UDPClient2.Disconnect())
                        {
                            Console.WriteLine("Failed to disconnect UDPClient2!");
                        }
                    }

                    if (!UDPClient1.Disconnect())
                    {
                        Console.WriteLine("Failed to disconnect UDPClient1!");
                    }
                }
                else
                {
                    Console.WriteLine("Failed to connect UDPClient1!");
                }

                if (!TheUDPServer.Stop())
                {
                    Console.WriteLine("Failed to stop UDP server!");
                }
            }
            else
            {
                Console.WriteLine("Failed to start UDP server!");
            }

            Console.WriteLine("---------------------------");
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }

        static void TheUDPServer_OnMessageReceived(MessageReceivedEventArgs e)
        {
            Type MessageType = e.TheMessage.GetType();
            if (MessageType == typeof(TestMessage))
            {
                TestMessage TheMessage = (TestMessage)e.TheMessage;
                Console.WriteLine("UDP server message receieved : " + MessageType.Name + " : ");
                Console.WriteLine(TheMessage.StringTest + " : " + TheMessage.NumberTest);
            }
        }
        static void TheUDPServer_OnMaxConnections(MaxConnectionsEventArgs e)
        {
            Console.WriteLine("UDP Server max connections reached.");
        }
        static void TheUDPServer_OnError(ErrorEventArgs e)
        {
            Console.Write(e.TheException.Message);
        }
        static void TheUDPServer_OnClientDisconnect(ClientDisconnectEventArgs e)
        {
            Console.WriteLine("UDP Server client disconnected.");
        }
        static void TheUDPServer_OnClientConnect(ClientConnectEventArgs e)
        {
            Console.WriteLine("UDP Server client connected.");
        }

        static void UDPClient1_OnError(ErrorEventArgs e)
        {
            Console.Write(e.TheException.Message);
        }
        static void UDPClient1_OnDisconnect(ClientDisconnectEventArgs e)
        {
            Console.WriteLine("UDP Client 1 disconnected.");
        }
        static void UDPClient1_OnConnect(ClientConnectEventArgs e)
        {
            Console.WriteLine("UDP Client 1 connected.");
        }
        static void UDPClient1_OnMessageReceived(MessageReceivedEventArgs e)
        {
            Type MessageType = e.TheMessage.GetType();
            if (MessageType == typeof(TestMessage))
            {
                TestMessage TheMessage = (TestMessage)e.TheMessage;
                Console.WriteLine("UDP Client 1 message receieved : " + MessageType.Name + " : ");
                Console.WriteLine(TheMessage.StringTest + " : " + TheMessage.NumberTest);
            }
        }

        static void UDPClient2_OnError(ErrorEventArgs e)
        {
            Console.Write(e.TheException.Message);
        }
        static void UDPClient2_OnDisconnect(ClientDisconnectEventArgs e)
        {
            Console.WriteLine("UDP Client 2 disconnected.");
        }
        static void UDPClient2_OnConnect(ClientConnectEventArgs e)
        {
            Console.WriteLine("UDP Client 2 connected.");
        }
        static void UDPClient2_OnMessageReceived(MessageReceivedEventArgs e)
        {
            Type MessageType = e.TheMessage.GetType();
            if (MessageType == typeof(TestMessage))
            {
                TestMessage TheMessage = (TestMessage)e.TheMessage;
                Console.WriteLine("UDP Client 2 message receieved : " + MessageType.Name + " : ");
                Console.WriteLine(TheMessage.StringTest + " : " + TheMessage.NumberTest);
            }
        }

    }
}
